package com.yuanqi.java.controller;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yuanqi.java.dto.BindProductsRequest;
import com.yuanqi.java.dto.CreateSupplierRequest;
import com.yuanqi.java.dto.UpdateSupplierRequest;
import com.yuanqi.java.entity.Product;
import com.yuanqi.java.entity.Supplier;
import com.yuanqi.java.entity.CommodityCategory;
import com.yuanqi.java.mapper.ProductMapper;
import com.yuanqi.java.mapper.CommodityCategoryMapper;
import com.yuanqi.java.service.ISupplierService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.server.ResponseStatusException;

import javax.transaction.Transactional;
import javax.validation.Valid;
import java.beans.FeatureDescriptor;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 * 供应商 前端控制器
 * </p>
 *
 * @author author
 * @since 2025-08-26
 */
@RestController
@RequestMapping("/supplier")
public class SupplierController {
    @Autowired
    private ISupplierService supplierService;
    @Autowired
    private ProductMapper productMapper;
    @Autowired
    private CommodityCategoryMapper categoryMapper;
    // 新增供应商
    @PostMapping("/add")
    public Supplier create(@Valid @RequestBody CreateSupplierRequest req) {
        Supplier s = new Supplier();
        BeanUtils.copyProperties(req, s);
        supplierService.save(s);
        return s;
    }

    // 供应商详情
    @GetMapping("/{id}")
    public Supplier detail(@PathVariable Long id) {
        Supplier s = supplierService.getById(id);
        if (s == null) throw new ResponseStatusException(HttpStatus.NOT_FOUND, "供应商不存在");
        return s;
    }

    // 删除供应商（并可选解除其下产品的绑定）
    @DeleteMapping("/{id}")
    @Transactional
    public void delete(@PathVariable Long id) {
        Supplier s = supplierService.getById(id);
        if (s == null) return;
        UpdateWrapper<Product> uw = new UpdateWrapper<>();
        uw.eq("supplier_code", s.getSupplierCode()).set("supplier_code", null);
        productMapper.update(null, uw);
        supplierService.removeById(id);
    }

    // 修改供应商
    @PutMapping("/{id}")
    public Supplier update(@PathVariable Long id, @RequestBody UpdateSupplierRequest req) {
        Supplier s = supplierService.getById(id);
        if (s == null) throw new ResponseStatusException(HttpStatus.NOT_FOUND);
        BeanUtils.copyProperties(req, s, getNullProps(req));
        supplierService.updateById(s);
        return s;
    }

    // 供应商列表（分页与条件查询）
    @GetMapping
    public IPage<Supplier> page(@RequestParam(defaultValue = "1") long pageNum,
                                @RequestParam(defaultValue = "10") long pageSize,
                                @RequestParam(required = false) String keyword,
                                @RequestParam(required = false) Integer status,
                                @RequestParam(required = false) String supplierCode) {
        Page<Supplier> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<Supplier> qw = Wrappers.lambdaQuery(Supplier.class)
                .eq(StringUtils.hasText(supplierCode), Supplier::getSupplierCode, supplierCode)
                .like(!StringUtils.hasText(supplierCode) && StringUtils.hasText(keyword), Supplier::getSupplierName, keyword)
                .eq(status != null, Supplier::getStatus, status)
                .orderByDesc(Supplier::getCreatedAt);
        return supplierService.page(page, qw);
    }

    // 产品关联：把给定产品绑定到该供应商
    @PostMapping("/{id}/products:bind")
    public void bindProducts(@PathVariable Long id, @Valid @RequestBody BindProductsRequest req) {
        supplierService.bindProducts(id, req.getProductIds());
    }

    // 查看该供应商下的产品（携带类目名称）
    @GetMapping("/{id}/products")
    public List<Product> listProducts(@PathVariable Long id) {
        Supplier s = supplierService.getById(id);
        if (s == null) throw new ResponseStatusException(HttpStatus.NOT_FOUND);
        List<Product> items = productMapper.selectList(
                Wrappers.<Product>lambdaQuery().eq(Product::getSupplierCode, s.getSupplierCode()));
        // 组装类目名称（支持 category_id 和 category_code 两种）
        Set<Long> catIds = items.stream().map(Product::getCategoryId).filter(v -> v != null && v > 0).collect(Collectors.toSet());
        Set<String> catCodes = items.stream().map(Product::getCategoryCode).filter(code -> code != null && !code.isEmpty()).collect(Collectors.toSet());
        if (!catIds.isEmpty() || !catCodes.isEmpty()) {
            List<CommodityCategory> cats;
            if (!catIds.isEmpty()) {
                cats = categoryMapper.selectList(Wrappers.<CommodityCategory>lambdaQuery().in(CommodityCategory::getId, catIds));
            } else {
                cats = categoryMapper.selectList(Wrappers.<CommodityCategory>lambdaQuery().in(CommodityCategory::getCategoryCode, catCodes));
            }
            Map<Long, String> idToName = cats.stream().collect(Collectors.toMap(CommodityCategory::getId, CommodityCategory::getCategoryName, (a,b)->a));
            Map<String, String> codeToName = cats.stream().collect(Collectors.toMap(CommodityCategory::getCategoryCode, CommodityCategory::getCategoryName, (a,b)->a));
            items.forEach(p -> {
                if (p.getCategoryId() != null && idToName.containsKey(p.getCategoryId())) {
                    p.setCategoryName(idToName.get(p.getCategoryId()));
                } else if (p.getCategoryCode() != null) {
                    p.setCategoryName(codeToName.get(p.getCategoryCode()));
                }
            });
        }
        return items;
    }

    private static String[] getNullProps(Object source) {
        BeanWrapper src = new BeanWrapperImpl(source);
        return Arrays.stream(src.getPropertyDescriptors())
                .map(FeatureDescriptor::getName)
                .filter(name -> src.getPropertyValue(name) == null)
                .toArray(String[]::new);
    }
}